// nbmade-modules/nbmade-iot/src/main/java/com/nbcio/iot/service/NodeRedService.java
package com.nbcio.iot.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.nbcio.iot.domain.entity.IotNodeRedFlow;
import com.nbcio.iot.mapper.IotNodeRedFlowMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class NodeRedService {

    private final IotNodeRedFlowMapper flowMapper;
    private final ObjectMapper objectMapper = new ObjectMapper();
    
    // 内存中存储运行中的 Flow 状态
    private final Map<Long, String> flowStatusMap = new ConcurrentHashMap<>();
    // 最近一次部署的Flow配置（简化：提供给运行时用）
    private volatile Map<String, Object> lastDeployedFlowConfig = new HashMap<>();

    public void deployFlow(IotNodeRedFlow flow) {
        try {
            // 解析 Flow 配置
            JsonNode flowConfig = objectMapper.readTree(flow.getFlowConfig());
            lastDeployedFlowConfig = objectMapper.convertValue(flowConfig, Map.class);
            
            // 启动 Flow（这里简化实现，实际应该调用 Node-RED API）
            flowStatusMap.put(flow.getFlowId(), "running");
            
            // 更新数据库状态
            flow.setIsRunning(true);
            flow.setIsActive(true);
            flowMapper.updateById(flow);
            
            log.info("Flow {} deployed successfully", flow.getFlowName());
        } catch (Exception e) {
            log.error("Failed to deploy flow {}: {}", flow.getFlowName(), e.getMessage());
            throw new RuntimeException("Flow 部署失败", e);
        }
    }

    public void stopFlow(Long flowId) {
        try {
            flowStatusMap.remove(flowId);
            
            IotNodeRedFlow flow = flowMapper.selectById(flowId);
            if (flow != null) {
                flow.setIsRunning(false);
                flowMapper.updateById(flow);
            }
            
            log.info("Flow {} stopped", flowId);
        } catch (Exception e) {
            log.error("Failed to stop flow {}: {}", flowId, e.getMessage());
        }
    }

    public String getFlowStatus(Long flowId) {
        return flowStatusMap.getOrDefault(flowId, "stopped");
    }

    public void importFlow(String flowJson) {
        try {
            JsonNode flowNode = objectMapper.readTree(flowJson);
            
            IotNodeRedFlow flow = new IotNodeRedFlow();
            flow.setFlowName(flowNode.get("name").asText());
            flow.setFlowDescription(flowNode.get("description").asText());
            flow.setFlowConfig(flowJson);
            flow.setIsActive(false);
            flow.setIsRunning(false);
            flow.setVersion(1);
            
            flowMapper.insert(flow);
            log.info("Flow {} imported successfully", flow.getFlowName());
        } catch (Exception e) {
            log.error("Failed to import flow: {}", e.getMessage());
            throw new RuntimeException("Flow 导入失败", e);
        }
    }

    public String exportFlow(Long flowId) {
        IotNodeRedFlow flow = flowMapper.selectById(flowId);
        if (flow == null) {
            throw new RuntimeException("Flow 不存在");
        }
        return flow.getFlowConfig();
    }

    public String getEditorUrl() {
        // 返回内嵌编辑器 URL
        return "/iot/nodered-editor";
    }

    public Map<String, Object> getLastDeployedFlowConfig() {
        return lastDeployedFlowConfig;
    }

    /**
     * 根据 flowId 获取已保存的 Flow 配置（Map 形式）。
     */
    public Map<String, Object> getFlowConfigById(Long flowId) {
        if (flowId == null) return null;
        IotNodeRedFlow flow = flowMapper.selectById(flowId);
        if (flow == null || Boolean.FALSE.equals(flow.getIsActive())) return null;
        try {
            JsonNode flowConfig = objectMapper.readTree(flow.getFlowConfig());
            return objectMapper.convertValue(flowConfig, Map.class);
        } catch (Exception e) {
            log.error("parse flow config error, flowId={}", flowId, e);
            return null;
        }
    }

    /**
     * 获取全局默认且激活的 Flow 配置（若存在）。
     */
    public Map<String, Object> getDefaultActiveFlowConfig() {
        IotNodeRedFlow probe = new IotNodeRedFlow();
        probe.setIsDefault(true);
        probe.setIsActive(true);
        IotNodeRedFlow flow = flowMapper.selectOne(new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<IotNodeRedFlow>()
            .eq(IotNodeRedFlow::getIsDefault, true)
            .eq(IotNodeRedFlow::getIsActive, true)
            .last("limit 1"));
        if (flow == null) return null;
        try {
            JsonNode flowConfig = objectMapper.readTree(flow.getFlowConfig());
            return objectMapper.convertValue(flowConfig, Map.class);
        } catch (Exception e) {
            log.error("parse default flow config error", e);
            return null;
        }
    }

    /**
     * 判断规则流是否激活且运行中
     */
    public boolean isFlowActiveAndRunning(Long flowId) {
        if (flowId == null) {
            return false;
        }
        IotNodeRedFlow flow = flowMapper.selectById(flowId);
        return flow != null && Boolean.TRUE.equals(flow.getIsActive()) && Boolean.TRUE.equals(flow.getIsRunning());
    }

    /**
     * 获取所有激活且运行中的规则ID集合
     */
    public Set<Long> getActiveRunningFlowIds() {
        return flowMapper.selectList(new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<IotNodeRedFlow>()
            .eq(IotNodeRedFlow::getIsActive, true)
            .eq(IotNodeRedFlow::getIsRunning, true))
            .stream()
            .map(IotNodeRedFlow::getFlowId)
            .collect(Collectors.toSet());
    }
}
